package com.windward.vii.service;

import com.github.pagehelper.PageHelper;
import com.windward.vii.common.Constants;
import com.windward.vii.common.JsonResult;
import com.windward.vii.common.ResultCode;
import com.windward.vii.dao.entity.AssetUserRecharge;
import com.windward.vii.dao.entity.Goods;
import com.windward.vii.dao.entity.Order;
import com.windward.vii.dao.mapper.AssetPlatformAccountMapper;
import com.windward.vii.dao.mapper.AssetUserAccountMapper;
import com.windward.vii.dao.mapper.AssetUserRechargeMapper;
import com.windward.vii.dao.mapper.OrderMapper;
import com.windward.vii.service.weixin.WeixinPayService;
import com.windward.vii.service.weixin.bean.OrderRequest;
import com.windward.vii.service.weixin.bean.OrderResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.util.*;

@Component
public class OrderService {

    private static Logger logger = LoggerFactory.getLogger(OrderService.class);

    @Autowired
    PlatformTransactionManager transactionManager;
    @Resource
    GoodsService goodsService;
    @Resource
    OrderMapper orderMapper;
    @Resource
    WeixinPayService weixinPayService;
    @Resource
    AssetUserAccountMapper assetUserAccountMapper;
    @Resource
    AssetUserRechargeMapper assetUserRechargeMapper;
    @Resource
    AssetPlatformAccountMapper assetPlatformAccountMapper;

    public Order selectBySn(String sn) {
        if(StringUtils.isNotBlank(sn)) {
            return orderMapper.selectBySn(sn);
        }
        return null;
    }

    public Order selectByOuterSn(String outTradeNo) {
        if(StringUtils.isNotBlank(outTradeNo)) {
            return orderMapper.selectByOutTradeNo(outTradeNo);
        }
        return null;
    }

    public int updateByPrimaryKeySelective(Order order) {
        return orderMapper.updateByPrimaryKeySelective(order);
    }

    public JsonResult createOrderForApplePay(Long uid, Goods goods, String receiptData, String ip) {
        logger.info("createOrderForApplePay: uid={}, goodsId={}", uid, goods.getId());
        try {
            // 创建业务订单
            Order paymentOrder = this.wrapOrder(uid, goods, Constants.Order.PAY_TYPE_APPLE, ip);
            paymentOrder.setOutTradeNo(receiptData);
            paymentOrder.setStatus(Constants.Order.ORDER_STATUS_PAY_SUCCESS);
            paymentOrder.setPayStatus(Constants.Order.PAY_STATUS_SUCCESS);
            paymentOrder.setPayTime(new Date());
            paymentOrder.setDeliverStatus(Constants.Order.DELIVER_STATUS_AWAITING);
            paymentOrder.setUpdateTime(new Date());
            paymentOrder.setTerminalType(goods.getTerminalType());
            if(orderMapper.insertSelective(paymentOrder) < 1) {
                logger.error("createOrderForApplePay: orderMapper.insertSelective < 1");
                return JsonResult.error();
            }

            // 返回订单结果
            JsonResult response = JsonResult.success();
            response.setBody(paymentOrder);
            logger.info("createOrderForApplePay success");
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("createOrderForApplePay exception: userId={}, exception={}", uid, e.getMessage());
            return JsonResult.error("创建订单失败");
        }
    }

    public JsonResult createOrderForWeixinPay(Long uid, Goods goods, String ip) {
        logger.info("createOrderForWeixinPay: uid={}, goodsId={}", uid, goods.getId());
        try {
            // 创建业务订单
            Order order = this.wrapOrder(uid, goods, Constants.Order.PAY_TYPE_WEIXIN, ip);
            if(orderMapper.insertSelective(order) < 1) {
                logger.error("createOrderForWeixinPay: orderMapper.insertSelective < 1");
                return JsonResult.error();
            }

            // 生成微信预支付订单
            OrderRequest orderRequest = weixinPayService.createOrderRequest(order);
            JsonResult weixinOrderResult = weixinPayService.unifiedOrder(orderRequest);
            if(weixinOrderResult.getCode() != ResultCode.SUCCESS_CODE) {
                // 更新业务订单状态为失败
                Order updateOrder = new Order();
                updateOrder.setIp(order.getIp());
                updateOrder.setUpdateTime(new Date());
                updateOrder.setStatus(Constants.Order.ORDER_STATUS_PAY_FAILED);
                orderMapper.updateByPrimaryKeySelective(updateOrder);
                logger.error("createOrderForWeixinPay: weixinPayService.unifiedOrder err={}", weixinOrderResult.getBody());
                return weixinOrderResult;
            }

            // 返回微信预支付订单结果
            OrderResponse orderResponse = (OrderResponse) weixinOrderResult.getBody();
            TreeMap<String,String> map = new TreeMap<String,String>();
            map.put("appid",orderResponse.getAppid());
            map.put("partnerid",orderResponse.getMch_id());
            map.put("prepayid",orderResponse.getPrepay_id());
            map.put("package","Sign=WXPay");
            map.put("noncestr",orderResponse.getNonce_str());
            map.put("timestamp",String.valueOf(new Date().getTime()/1000));
            map.put("sign", weixinPayService.generateSign(map));
            map.put("sn",order.getSn());

            JsonResult response = JsonResult.success();
            response.setBody(map);
            logger.info("createOrderForWeixinPay success");
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("createOrderForWeixinPay exception: userId={}, exception={}", uid, e.getMessage());
            return JsonResult.error("创建订单失败");
        }
    }

    /**
     * 充值成功回调：更新订单状态、添加账户余额
     * @param paymentOrder 数据库订单
     * @param outerTradeNo 微信/支付宝回执订单号
     * @return
     */
    public JsonResult paySuccess(Order paymentOrder, String outerTradeNo) {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = transactionManager.getTransaction(def);

        boolean isRechargeSuccess = false;

        try {
            // 更新订单状态
            Order updateOrder = new Order();
            updateOrder.setId(paymentOrder.getId());
            updateOrder.setOutTradeNo(outerTradeNo); // 微信回执订单号
            updateOrder.setStatus(Constants.Order.ORDER_STATUS_DELIVER_SUCCESS);
            updateOrder.setPayStatus(Constants.Order.PAY_STATUS_SUCCESS);
            updateOrder.setDeliverStatus(Constants.Order.DELIVER_STATUS_SUCCESS);
            updateOrder.setUpdateTime(new Date());
            if(orderMapper.updateByPrimaryKeySelective(updateOrder) < 1) {
                return JsonResult.error("更新订单状态失败");
            }



            // 生成充值成功记录
            AssetUserRecharge assetUserRecharge = new AssetUserRecharge();
            assetUserRecharge.setUid(paymentOrder.getUid());
            assetUserRecharge.setOrderId(paymentOrder.getId());
            assetUserRecharge.setPayType(paymentOrder.getPayType());
            assetUserRecharge.setAmount(paymentOrder.getAmount());
            assetUserRecharge.setCoin(paymentOrder.getCoin());
            assetUserRecharge.setTerminalType(paymentOrder.getTerminalType());
            assetUserRecharge.setCreateTime(new Date());
            if(assetUserRechargeMapper.insertSelective(assetUserRecharge) < 1) {
                return JsonResult.error("生成充值成功记录失败");
            }

            // 添加账户虚拟币
            if(assetUserAccountMapper.recharge(paymentOrder.getUid(), paymentOrder.getCoin()) < 1) {
                return JsonResult.error("添加账户余额失败");
            }

            // 添加系统账户余额
            if(assetPlatformAccountMapper.recharge(paymentOrder.getAmount()) < 1) {
                return JsonResult.error("添加系统账户余额失败");
            }

            isRechargeSuccess = true;
            return JsonResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("三方充值回调发生异常：sn={}, e={}", paymentOrder.getSn(), e.getMessage());
            return JsonResult.error("充值回调发生异常");
        } finally {
            if(isRechargeSuccess) {
                transactionManager.commit(status);
            } else {
                transactionManager.rollback(status);
            }
        }
    }

    public void payFail(Order paymentOrder) {
        // 更新业务订单状态为失败
        Order updateOrder = new Order();
        updateOrder.setIp(paymentOrder.getIp());
        updateOrder.setUpdateTime(new Date());
        updateOrder.setStatus(Constants.Order.ORDER_STATUS_DELIVER_SUCCESS);
        updateOrder.setOutTradeNo(paymentOrder.getOutTradeNo());
        orderMapper.updateByPrimaryKeySelective(updateOrder);
    }

    private Order wrapOrder(Long uid, Goods goods, int payType, String ip) {
        Order order = new Order();

        order.setUid(uid);
        order.setPayType(payType);
        order.setIp(ip);

        order.setGoodsId(goods.getId());
        order.setGoodsSn(goods.getSn());
        order.setGoodsName(goods.getName());
        order.setGoodsPrice(goods.getPrice());
        order.setGoodsNum(1);
        order.setGoodsIcon(goods.getIcon());
        order.setGoodsCoin(goods.getCoin());
        order.setTerminalType(goods.getTerminalType());

        Date currTime = new Date();
        order.setCreateTime(currTime);
        order.setUpdateTime(currTime);
        order.setExpireTime(DateUtils.addMinutes(currTime, WeixinPayService.EFFECT_TIME_MINUTES));

        order.setStatus(Constants.Order.ORDER_STATUS_INIT);
        order.setPayStatus(Constants.Order.PAY_STATUS_AWAITING);
        order.setDeliverStatus(Constants.Order.DELIVER_STATUS_AWAITING);

        order.setAmount(goods.getPrice() * order.getGoodsNum());
        order.setCoin(goods.getCoin() * order.getGoodsNum());
        order.setSn(genOrderSn());

        return order;
    }

    private static String genOrderSn(){
        try {
            return DigestUtils.md5DigestAsHex(UUID.randomUUID().toString().getBytes("UTF-8")).toUpperCase();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

//    public JsonResult save(Order Order) {
//        int row = orderMapper.insertSelective(Order);
//        return row > 0 ? JsonResult.success() : JsonResult.error();
//    }

    public List<Order> getUserOrderPageList(Long uid, Integer pageNum, Integer pageSize) {
        pageNum = pageNum == null ? 1 : pageNum;
        pageSize = pageSize == null ? 10 : pageSize;
        PageHelper.startPage(pageNum, pageSize);
        return orderMapper.getUserOrderPageList(uid);
    }

    public static void main(String[] args) {
        for(int i = 0; i < 10; i++) {
            String sn = genOrderSn();
            System.out.println(sn);
            System.out.println("length=" + sn.length());
        }

        System.out.println(Math.toIntExact(10000));
    }



//    public JsonResult applePayVerify(Long uid, String orderSn, String receiptData, String ip) {
//        Goods goods = goodsService.getBySn(orderSn);
//        if(goods == null) {
//            return new JsonResult(ResultCode.PARAM_ERROR_CODE, "购买商品不存在");
//        }
//        JsonResult<Order> orderResult = createOrderForApplePay(uid, goods, receiptData, ip);
//        if(orderResult.getCode() != ResultCode.SUCCESS_CODE) {
//            return orderResult;
//        }
//        Order paymentOrder = orderResult.getBody();
//
//        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
//        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//        TransactionStatus status = transactionManager.getTransaction(def);
//
//        boolean isRechargeSuccess = false;
//
//        try {
//            // 更新订单状态
//            Order updateOrder = new Order();
//            updateOrder.setId(paymentOrder.getId());
//            // updateOrder.setOutTradeNo(outerTradeNo); // 微信回执订单号
//            updateOrder.setStatus(Constants.Order.ORDER_STATUS_DELIVER_SUCCESS);
//            updateOrder.setPayStatus(Constants.Order.PAY_STATUS_SUCCESS);
//            updateOrder.setDeliverStatus(Constants.Order.DELIVER_STATUS_SUCCESS);
//            updateOrder.setUpdateTime(new Date());
//            if(orderMapper.updateByPrimaryKeySelective(updateOrder) < 1) {
//                return JsonResult.error("更新订单状态失败");
//            }
//
//            // 生成充值成功记录
//            AssetUserRecharge assetUserRecharge = new AssetUserRecharge();
//            assetUserRecharge.setUid(paymentOrder.getUid());
//            assetUserRecharge.setOrderId(paymentOrder.getId());
//            assetUserRecharge.setPayType(paymentOrder.getPayType());
//            assetUserRecharge.setAmount(paymentOrder.getAmount());
//            assetUserRecharge.setCoin(paymentOrder.getCoin());
//            assetUserRecharge.setTerminalType(paymentOrder.getTerminalType());
//            assetUserRecharge.setCreateTime(new Date());
//            if(assetUserRechargeMapper.insertSelective(assetUserRecharge) < 1) {
//                return JsonResult.error("生成充值成功记录失败");
//            }
//
//            // 添加账户虚拟币
//            if(assetUserAccountMapper.recharge(paymentOrder.getUid(), paymentOrder.getCoin()) < 1) {
//                return JsonResult.error("添加账户余额失败");
//            }
//
//            // 添加系统账户余额
//            if(assetPlatformAccountMapper.recharge(paymentOrder.getAmount()) < 1) {
//                return JsonResult.error("添加系统账户余额失败");
//            }
//
//            isRechargeSuccess = true;
//            return JsonResult.success();
//        } catch (Exception e) {
//            e.printStackTrace();
//            logger.error("三方充值回调发生异常：sn={}, e={}", paymentOrder.getSn(), e.getMessage());
//            return JsonResult.error("充值回调发生异常");
//        } finally {
//            if(isRechargeSuccess) {
//                transactionManager.commit(status);
//            } else {
//                transactionManager.rollback(status);
//            }
//        }
//    }
}
